<?php
/**
 * File containing the RandomStringProcessor
 *
 * PHP Version 5
 *
 * @category Processors
 * @package  Processors
 * @author   Martin Schlecht <herrlollinger@gmail.com>
 * @license  MIT License
 * @link     http://code.google.com/p/universal-test-data
 */

/**
 * Processor class "RandomStringProcessor"
 *
 * Processor which is used to process tags which implements random strings within the text.
 *
 * @category   Processors
 * @package    Processors
 * @subpackage RandomStringProcessors
 * @author     Martin Schlecht <herrlollinger@gmail.com>
 * @copyright  see @author
 * @license    MIT License
 * @link       http://code.google.com/p/universal-test-data
 *
 * The followings are the available attributes of the processor class
 * @property string $text, the text which should be processed
 */
class RandomStringProcessor
{
	private $text;
	
	/**
	 * Processes the given text and replaces the tags with the random values, the values can be repeated
	 *
	 * @param String $text, the text to process
	 *
	 * @return String
	 */
	public function process($text) {
		$this->text = $text;
		
		preg_match_all("#\s*{(.*?)}#si", $this->text, $matches);
		
		foreach ($matches[1] AS $m) {
			$string = "{" . $m . "}";
			$m = explode(":", $m);
			
			/**
			 * {randomString:10,5}
			 * Random string with lenght 10, n times repeated
			 */
			if ($m[0] == "randomString") {
				$parameter = explode(",", $m[1]);
				
				if (!isset($parameter[0]) || !is_numeric($parameter[0])) {
					$parameter[0] = 10;
				}
				
				if (!isset($parameter[1]) || !is_numeric($parameter[1])) {
					$parameter[1] = 1;
				}
				
				$this->text = str_replace($string, $this->manageRepeation($this->randomString($parameter[0]), $string, $parameter[1]), $this->text);
			}
			
			/**
			 * {randomStringUpper:10,5}
			 * Random string with lenght 10 uppercase, n times repeated
			 */
			if ($m[0] == "randomStringUpper") {
				$parameter = explode(",", $m[1]);
				
				if (!isset($parameter[0]) || !is_numeric($parameter[0])) {
					$parameter[0] = 10;
				}
				
				if (!isset($parameter[1]) || !is_numeric($parameter[1])) {
					$parameter[1] = 1;
				}
				
				$this->text = str_replace($string, $this->manageRepeation(strtoupper($this->randomString($parameter[0])), $string, $parameter[1]), $this->text);
			}
			
			/**
			 * {randomStringLower:10,5}
			 * Random string with lenght 10 lowercase, n times repeated
			 */
			if ($m[0] == "randomStringLower") {
				$parameter = explode(",", $m[1]);
				
				if (!isset($parameter[0]) || !is_numeric($parameter[0])) {
					$parameter[0] = 10;
				}
				
				if (!isset($parameter[1]) || !is_numeric($parameter[1])) {
					$parameter[1] = 1;
				}
				
				$this->text = str_replace($string, $this->manageRepeation(strtolower($this->randomString($parameter[0])), $string, $parameter[1]), $this->text);
			}
			
			/**
			 * {randomNumberString:10,5}
			 * Random string/number with lenght 10, n times repeated
			 */
			if ($m[0] == "randomNumberString") {
				$parameter = explode(",", $m[1]);
				
				if (!isset($parameter[0]) || !is_numeric($parameter[0])) {
					$parameter[0] = 10;
				}
				
				if (!isset($parameter[1]) || !is_numeric($parameter[1])) {
					$parameter[1] = 1;
				}
				
				$this->text = str_replace($string, $this->manageRepeation($this->randomNumberString($parameter[0]), $string, $parameter[1]), $this->text);
			}
			
			/**
			 * {randomNumberStringUpper:10,5}
			 * Random string/number with lenght 10 uppercase, n times repeated
			 */
			if ($m[0] == "randomNumberStringUpper") {
				$parameter = explode(",", $m[1]);
				
				if (!isset($parameter[0]) || !is_numeric($parameter[0])) {
					$parameter[0] = 10;
				}
				
				if (!isset($parameter[1]) || !is_numeric($parameter[1])) {
					$parameter[1] = 1;
				}
				
				$this->text = str_replace($string, $this->manageRepeation(strtoupper($this->randomNumberString($parameter[0])), $string, $parameter[1]), $this->text);
			}
			
			/**
			 * {randomNumberStringLower:10,5}
			 * Random string/number with lenght 10 lowercase, n times repeated
			 */
			if ($m[0] == "randomNumberStringLower") {
				$parameter = explode(",", $m[1]);
				
				if (!isset($parameter[0]) || !is_numeric($parameter[0])) {
					$parameter[0] = 10;
				}
				
				if (!isset($parameter[1]) || !is_numeric($parameter[1])) {
					$parameter[1] = 1;
				}
				
				$this->text = str_replace($string, $this->manageRepeation(strtolower($this->randomNumberString($parameter[0])), $string, $parameter[1]), $this->text);
			}
			
			/**
			 * {randomStringRange:5,10,5}
			 * Random string with lenght between 5 and 10, n times repeated
			 */
			if ($m[0] == "randomStringRange") {
				$parameter = explode(",", $m[1]);
				
				if (!isset($parameter[0]) || !is_numeric($parameter[0])) {
					$parameter[0] = 5;
				}
				
				if (!isset($parameter[1]) || !is_numeric($parameter[1])) {
					$parameter[1] = 10;
				}
				
				if (!isset($parameter[2]) || !is_numeric($parameter[2])) {
					$parameter[2] = 1;
				}
				
				$this->text = str_replace($string, $this->manageRepeation($this->randomStringRange($parameter[0], $parameter[1]), $string, $parameter[2]), $this->text);
			}
			
			/**
			 * {randomStringRangeUpper:5,10,5}
			 * Random string with lenght between 5 and 10, n times repeated
			 */
			if ($m[0] == "randomStringRangeUpper") {
				$parameter = explode(",", $m[1]);
				
				if (!isset($parameter[0]) || !is_numeric($parameter[0])) {
					$parameter[0] = 5;
				}
				
				if (!isset($parameter[1]) || !is_numeric($parameter[1])) {
					$parameter[1] = 10;
				}
				
				if (!isset($parameter[2]) || !is_numeric($parameter[2])) {
					$parameter[2] = 1;
				}
				
				$this->text = str_replace($string, $this->manageRepeation(strtoupper($this->randomStringRange($parameter[0], $parameter[1])), $string, $parameter[2]), $this->text);
			}
			
			/**
			 * {randomStringRangeLower:5,10,5}
			 * Random string with lenght between 5 and 10, n times repeated
			 */
			if ($m[0] == "randomStringRangeLower") {
				$parameter = explode(",", $m[1]);
				
				if (!isset($parameter[0]) || !is_numeric($parameter[0])) {
					$parameter[0] = 5;
				}
				
				if (!isset($parameter[1]) || !is_numeric($parameter[1])) {
					$parameter[1] = 10;
				}
				
				if (!isset($parameter[2]) || !is_numeric($parameter[2])) {
					$parameter[2] = 1;
				}
				
				$this->text = str_replace($string, $this->manageRepeation(strtolower($this->randomStringRange($parameter[0], $parameter[1])), $string, $parameter[2]), $this->text);
			}
			
			/**
			 * {randomNumberStringRange:5,10,5}
			 * Random string/number with lenght between 5 and 10, n times repeated
			 */
			if ($m[0] == "randomNumberStringRange") {
				$parameter = explode(",", $m[1]);
				
				if (!isset($parameter[0]) || !is_numeric($parameter[0])) {
					$parameter[0] = 5;
				}
				
				if (!isset($parameter[1]) || !is_numeric($parameter[1])) {
					$parameter[1] = 10;
				}
				
				if (!isset($parameter[2]) || !is_numeric($parameter[2])) {
					$parameter[2] = 1;
				}
				
				$this->text = str_replace($string, $this->manageRepeation($this->randomNumberStringRange($parameter[0], $parameter[1]), $string, $parameter[2]), $this->text);
			}
			
			/**
			 * {randomNumberStringRangeUpper:5,10,5}
			 * Random string/number with lenght between 5 and 10, n times repeated
			 */
			if ($m[0] == "randomNumberStringRangeUpper") {
				$parameter = explode(",", $m[1]);
				
				if (!isset($parameter[0]) || !is_numeric($parameter[0])) {
					$parameter[0] = 5;
				}
				
				if (!isset($parameter[1]) || !is_numeric($parameter[1])) {
					$parameter[1] = 10;
				}
				
				if (!isset($parameter[2]) || !is_numeric($parameter[2])) {
					$parameter[2] = 1;
				}
				
				$this->text = str_replace($string, $this->manageRepeation(strtoupper($this->randomNumberStringRange($parameter[0], $parameter[1])), $string, $parameter[2]), $this->text);
			}
			
			/**
			 * {randomNumberStringRangeLower:5,10,5}
			 * Random string/number with lenght between 5 and 10, n times repeated
			 */
			if ($m[0] == "randomNumberStringRangeLower") {
				$parameter = explode(",", $m[1]);
				
				if (!isset($parameter[0]) || !is_numeric($parameter[0])) {
					$parameter[0] = 5;
				}
				
				if (!isset($parameter[1]) || !is_numeric($parameter[1])) {
					$parameter[1] = 10;
				}
				
				if (!isset($parameter[2]) || !is_numeric($parameter[2])) {
					$parameter[2] = 1;
				}
				
				$this->text = str_replace($string, $this->manageRepeation(strtolower($this->randomNumberStringRange($parameter[0], $parameter[1])), $string, $parameter[2]), $this->text);
			}
			
			/**
			 * {randomWords:10,2,9,5}
			 * Generates 10 random words, n times repeated
			 */
			if ($m[0] == "randomWords") {
				$parameter = explode(",", $m[1]);
				
				if (!isset($parameter[0]) || !is_numeric($parameter[0])) {
					$parameter[0] = 10;
				}
				
				if (!isset($parameter[1]) || !is_numeric($parameter[1])) {
					$parameter[1] = 2;
				}
				
				if (!isset($parameter[2]) || !is_numeric($parameter[2])) {
					$parameter[2] = 9;
				}
				
				if (!isset($parameter[3]) || !is_numeric($parameter[3])) {
					$parameter[3] = 1;
				}
				
				$replacement = "";
				
				for ($x = 0; $x <= $parameter[0]; $x++) {
					$replacement .= $this->randomStringRange($parameter[1], $parameter[2]) . " ";
				}
				
				$this->text = str_replace($string, $this->manageRepeation($replacement, $string, $parameter[3]), $this->text);
			}
			
			/**
			 * {randomWordsUpper:10,5}
			 * Generates 10 random words, n times repeated
			 */
			if ($m[0] == "randomWordsUpper") {
				$parameter = explode(",", $m[1]);
				
				if (!isset($parameter[0]) || !is_numeric($parameter[0])) {
					$parameter[0] = 10;
				}
				
				if (!isset($parameter[1]) || !is_numeric($parameter[1])) {
					$parameter[1] = 2;
				}
				
				if (!isset($parameter[2]) || !is_numeric($parameter[2])) {
					$parameter[2] = 9;
				}
				
				if (!isset($parameter[3]) || !is_numeric($parameter[3])) {
					$parameter[3] = 1;
				}
				
				$replacement = "";
				
				for ($x = 0; $x <= $parameter[0]; $x++) {
					$replacement .= $this->randomStringRange($parameter[1], $parameter[2]) . " ";
				}
				
				$this->text = str_replace($string, $this->manageRepeation(strtoupper($replacement), $string, $parameter[3]), $this->text);
			}
			
			/**
			 * {randomWordsLower:10,5}
			 * Generates 10 random words, n times repeated
			 */
			if ($m[0] == "randomWordsLower") {
				$parameter = explode(",", $m[1]);
				
				if (!isset($parameter[0]) || !is_numeric($parameter[0])) {
					$parameter[0] = 10;
				}
				
				if (!isset($parameter[1]) || !is_numeric($parameter[1])) {
					$parameter[1] = 2;
				}
				
				if (!isset($parameter[2]) || !is_numeric($parameter[2])) {
					$parameter[2] = 9;
				}
				
				if (!isset($parameter[3]) || !is_numeric($parameter[3])) {
					$parameter[3] = 1;
				}
				
				$replacement = "";
				
				for ($x = 0; $x <= $parameter[0]; $x++) {
					$replacement .= $this->randomStringRange($parameter[1], $parameter[2]) . " ";
				}
				
				$this->text = str_replace($string, $this->manageRepeation(strtolower($replacement), $string, $parameter[3]), $this->text);
			}
		}
		
		return $this->text;
	}
	
	/**
	 * The method generates a random string with a predefined lenght
	 *
	 * @param Integer $length The lenght of the requested string
	 *
	 * @return String
	 */
	public function randomString($length) {
		$string = "abcdefghijklmopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
		
		for ($x = 0; $x <= round($length / 52, 0); $x++) {
			$string .= "abcdefghijklmopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
		}
		
		$string = str_shuffle($string);
		
		return substr($string, 0, $length);
	}
	
	/**
	 * The method generates a random string with includes letters and numbers with a predefined lenght
	 *
	 * @param Integer $length The lenght of the requested string
	 *
	 * @return String
	 */
	public function randomNumberString($length) {
		$randomNumberProcessor = new RandomNumberProcessor();
		
		$number = $randomNumberProcessor->numberWithFixedLenght($length);
		$string = $this->randomString($length);
		
		$string = str_shuffle($number . $string);
		
		return substr($string, 0, $length);
	}
	
	/**
	 * The method returns a random string with a predefined lenght. The lenght are within a custom range
	 *
	 * @param Integer $min, the minimal lenght of the string
	 * @param Integer $max, the maximal lenght of the string
	 * 
	 * @return String
	 */
	public function randomStringRange($min, $max) {
		$randomNumberProcessor = new RandomNumberProcessor();
		
		return $this->randomString($randomNumberProcessor->randomNumber($min, $max));
	}
	
	/**
	 * The method returns a random string with can also include numbers with a predefined lenght. The lenght are within a custom range
	 *
	 * @param Integer $min, the minimal lenght of the string
	 * @param Integer $max, the maximal lenght of the string
	 * 
	 * @return String
	 */
	public function randomNumberStringRange($min, $max) {
		$randomNumberProcessor = new RandomNumberProcessor();
		
		return $this->randomNumberString($randomNumberProcessor->randomNumber($min, $max));
	}
	
	/**
	 * Manages the repeation of values
	 * 
	 * @param String $value,  the value which should be replaced
	 * @param String $string, the string for the cockie
	 * @param String $times,  the number of times the value should be repeated
	 * 
	 * @return String
	 */
	public function manageRepeation($value, $string, $times) {
		$replacement = "";
		
		if (Yii::app()->session[$string . "_times"] >= $times || !isset(Yii::app()->session[$string . "_times"])) {
			Yii::app()->session[$string . "_replacement"] = $value;
			Yii::app()->session[$string . "_times"] = 1;
							
			$replacement = $value;
		} else {
			$number = Yii::app()->session[$string . "_replacement"];
			$times = Yii::app()->session[$string . "_times"] + 1;
			
			Yii::app()->session[$string . "_times"] = $times;
			
			$replacement = $number;
		}
		
		Yii::app()->session['resetManager']->add($string . "_replacement");
		Yii::app()->session['resetManager']->add($string . "_times");
		
		return $replacement;
	}
	
	/**
	 * Returns the documentation
	 *
	 * @return String
	 */
	 public function documentation() {
		return array(
			array('{randomString:10,5}', 'Random string with lenght 10, n times repeated'), 
			array('{randomStringUpper:10,5}', 'Random string with lenght 10 uppercase, n times repeated'), 
			array('{randomStringLower:10,5}', 'Random string with lenght 10 lowercase, n times repeated'), 
			array('{randomNumberString:10,5}', 'Random string/number with lenght 10, n times repeated'), 
			array('{randomNumberStringUpper:10,5}', 'Random string/number with lenght 10 uppercase, n times repeated'), 
			array('{randomNumberStringLower:10,5}', 'Random string/number with lenght 10 lowercase, n times repeated'), 
			array('{randomStringRange:5,10,5}', 'Random string with lenght between 5 and 10, n times repeated'), 
			array('{randomStringRangeUpper:5,10,5}', 'Random string with lenght between 5 and 10 uppercase, n times repeated'), 
			array('{randomStringRangeLower:5,10,5}', 'Random string with lenght between 5 and 10 lowercase, n times repeated'), 
			array('{randomNumberStringRange:5,10,5}', 'Random string/number with lenght between 5 and 10, n times repeated'), 
			array('{randomNumberStringRangeUpper:5,10,5}', 'Random string/number with lenght between 5 and 10 uppercase, n times repeated'), 
			array('{randomNumberStringRangeLower:5,10,5}', 'Random string/number with lenght between 5 and 10 lowercase, n times repeated'), 
			array('{randomWords:10,5}', 'Generates 10 random words, n times repeated'), 
			array('{randomWordsUpper:10,5}', 'Generates 10 random words uppercase, n times repeated'), 
			array('{randomWordsLower:10,5}', 'Generates 10 random words lowercase, n times repeated'), 
		);
	 }
	 
	/**
	 * Prints the documentation
	 *
	 * @return string
	 */
	public function print_documentation() {
		foreach ($this->documentation() AS $docu) {
			echo '<span style="font-family:monospace;font-size:11px">' . $docu[0] . '</span><br/>' . $docu[1] . '<br/>';
		}
	}
}
?>